<template>
  <div class="sequence-image-container" :style="containerStyle">
    <div v-if="isLoading" class="loading-indicator">
      <div class="spinner"></div>
    </div>
    <img 
      v-if="currentImage"
      :src="currentImage" 
      class="sequence-image" 
      :style="{ opacity: imageError ? 0 : opacity, ...imageStyle }"
      @error="handleImageError"
      @load="handleImageLoad"
    />
    <slot></slot>
  </div>
</template>

<script>
import { ref, computed, onMounted, onUnmounted, onBeforeUnmount, watch } from 'vue'

export default {
  name: 'SequenceImage',
  props: {
    // 图片路径模式，使用{n}作为帧数占位符，例如：'/assets/images/sequence_{n}.webp'
    pathPattern: {
      type: String,
      required: true
    },
    // 总帧数
    frames: {
      type: Number,
      default: 100
    },
    // 帧率 (fps)
    frameRate: {
      type: Number,
      default: 10
    },
    // 是否自动播放
    autoPlay: {
      type: Boolean,
      default: true
    },
    // 是否循环播放
    loop: {
      type: Boolean,
      default: true
    },
    // 图片宽度
    width: {
      type: [String, Number],
      default: 'auto'
    },
    // 图片高度
    height: {
      type: [String, Number],
      default: 'auto'
    },
    // 是否使用import.meta.glob加载图片
    useGlob: {
      type: Boolean,
      default: false
    },
    // glob路径模式，例如：'@/assets/image/keyi/*.webp'
    globPattern: {
      type: String,
      default: ''
    },
    // 数字填充长度，例如：3表示001, 002, 003...
    padLength: {
      type: Number,
      default: 3
    },
    // 是否启用平滑过渡
    enableTransition: {
      type: Boolean,
      default: true
    }
  },
  emits: ['ready', 'frame-change', 'complete', 'error'],
  setup(props, { emit }) {
    const currentFrame = ref(0)
    const imageCache = ref([])
    const isAnimationReady = ref(false)
    const animationInterval = ref(null)
    let animationFrameId = null
    const opacity = ref(1)
    const imageError = ref(false)
    const isLoading = ref(true)
    
    // 计算容器样式
    const containerStyle = computed(() => {
      return {
        width: typeof props.width === 'number' ? `${props.width}px` : props.width,
        height: typeof props.height === 'number' ? `${props.height}px` : props.height,
      }
    })
    
    // 计算图片样式
    const imageStyle = computed(() => {
      return {
        width: '100%',
        height: '100%',
        objectFit: 'contain',
        transition: props.enableTransition ? 'opacity 0.2s ease-in-out' : 'none'
      }
    })

    // 当前显示的图片
    const currentImage = computed(() => {
      if (!isAnimationReady.value || imageCache.value.length === 0) {
        return ''
      }
      
      // 确保索引不超出范围
      const index = Math.min(currentFrame.value, imageCache.value.length - 1)
      return imageCache.value[index]
    })

    // 使用glob加载图片
    const loadImagesWithGlob = async () => {
      if (!props.globPattern) {
        console.error('Glob pattern is required when useGlob is true')
        emit('error', 'Glob pattern is required when useGlob is true')
        isLoading.value = false
        return
      }
      
      isLoading.value = true

      try {
        // 动态导入图片 - 不能使用变量作为glob参数
        // 改为使用预定义的模式，并根据props.globPattern进行过滤
        let images = {}
        
        // 预定义所有可能的glob模式
        const allImages = import.meta.glob('/public/**/*.webp', { eager: true })
        
        // 从globPattern中提取基本路径，用于过滤
        const patternBase = props.globPattern.replace(/^@/, '/public').replace(/\*\.webp$/, '')
        
        // 过滤出匹配的图片
        Object.keys(allImages).forEach(path => {
          if (path.startsWith(patternBase)) {
            images[path] = allImages[path]
          }
        })
        
        // 如果没有找到匹配的图片，尝试更宽松的匹配
        if (Object.keys(images).length === 0) {
          console.warn(`No images found with pattern ${props.globPattern}, trying broader match`)
          // 提取最后一个目录名作为匹配条件
          const lastDir = patternBase.split('/').filter(Boolean).pop()
          if (lastDir) {
            Object.keys(allImages).forEach(path => {
              if (path.includes(`/${lastDir}/`)) {
                images[path] = allImages[path]
              }
            })
          }
        }
        
        console.log(`[SequenceImage] Found ${Object.keys(images).length} images matching pattern ${props.globPattern}`)
        
        // 清空缓存
        imageCache.value = []
        isAnimationReady.value = false
        
        // 获取所有图片路径
        const imagePaths = Object.keys(images)
        
        // 对路径进行排序，确保按正确顺序加载
        imagePaths.sort((a, b) => {
          // 从路径中提取数字部分
          const numA = parseInt(a.match(/(\d+)\.webp$/)?.[1] || '0')
          const numB = parseInt(b.match(/(\d+)\.webp$/)?.[1] || '0')
          return numA - numB
        })
        
        console.log(`[SequenceImage] Found ${imagePaths.length} images`)
        
        // 预先分配数组空间
        const tempCache = new Array(imagePaths.length)
        let loadedCount = 0
        
        // 优先加载第一帧
        if (imagePaths.length > 0) {
          const firstPath = imagePaths[0]
          const firstImg = new Image()
          
          await new Promise((resolve) => {
            firstImg.onload = () => {
              // 立即更新缓存以显示第一帧
              const firstImgSrc = images[firstPath].default || images[firstPath]
              tempCache[0] = firstImgSrc
              imageCache.value = [firstImgSrc] // 立即更新缓存以显示第一帧
              isAnimationReady.value = true
              isLoading.value = false
              emit('ready', { loadedCount: 1, totalCount: imagePaths.length })
              resolve()
            }
            firstImg.onerror = () => {
              console.error(`[SequenceImage] Failed to load first image: ${firstPath}`)
              isLoading.value = false
              emit('error', `Failed to load first image: ${firstPath}`)
              resolve()
            }
            firstImg.src = images[firstPath].default || images[firstPath]
          })
        }
        
        // 加载剩余的图片
        if (imagePaths.length > 1) {
          const remainingPaths = imagePaths.slice(1)
          
          // 为剩余图片创建加载Promise
          const loadPromises = remainingPaths.map((path, index) => {
            return new Promise((resolve) => {
              const img = new Image()
              img.onload = () => {
                loadedCount++
                // 保持原始顺序 (index + 1 因为我们跳过了第一张图)
                tempCache[index + 1] = images[path].default || images[path]
                
                // 当加载了足够多的图片后，更新加载状态
                if (loadedCount >= Math.min(10, remainingPaths.length)) {
                  emit('ready', { loadedCount: loadedCount + 1, totalCount: imagePaths.length })
                }
                
                resolve()
              }
              img.onerror = () => {
                console.error(`[SequenceImage] Failed to load image: ${path}`)
                resolve()
              }
              img.src = images[path].default || images[path]
            })
          })
          
          // 等待所有剩余图片加载完成
          await Promise.all(loadPromises)
        }
        
        // 过滤掉未加载的图片并更新缓存
        imageCache.value = tempCache.filter(item => item !== undefined)
        console.log(`[SequenceImage] Successfully loaded ${imageCache.value.length} images`)
        emit('ready', { loadedCount: imageCache.value.length, totalCount: imagePaths.length })
      } catch (error) {
        console.error('[SequenceImage] Error loading images with glob:', error)
        isLoading.value = false
        emit('error', error)
      }
    }

    // 使用路径模式加载图片
    const loadImagesWithPattern = async () => {
      try {
        // 清空缓存
        imageCache.value = []
        isAnimationReady.value = false
        isLoading.value = true
        
        const tempCache = []
        let loadedCount = 0
        
        // 优先加载第一帧
        const firstFrameNumber = '1'.padStart(props.padLength, '0')
        const firstImgPath = props.pathPattern.startsWith('/') ? props.pathPattern.replace('{n}', firstFrameNumber) : `/${props.pathPattern.replace('{n}', firstFrameNumber)}`
        
        // 加载第一帧
        await new Promise((resolve) => {
          const img = new Image()
          img.onload = () => {
            tempCache[0] = firstImgPath
            imageCache.value = [firstImgPath] // 立即更新缓存以显示第一帧
            isAnimationReady.value = true
            isLoading.value = false
            emit('ready', { loadedCount: 1, totalCount: props.frames })
            resolve()
          }
          img.onerror = () => {
            console.error(`[SequenceImage] Failed to load first image: ${firstImgPath}`)
            imageError.value = true
            isLoading.value = false
            emit('error', `Failed to load first image: ${firstImgPath}`)
            resolve()
          }
          img.src = firstImgPath
        })
        
        // 创建加载Promise加载剩余帧
        const loadPromises = Array.from({ length: props.frames - 1 }, (_, i) => {
          return new Promise((resolve) => {
            const frameNumber = (i + 2).toString().padStart(props.padLength, '0')
            const imgPath = props.pathPattern.startsWith('/') ? props.pathPattern.replace('{n}', frameNumber) : `/${props.pathPattern.replace('{n}', frameNumber)}`
            
            const img = new Image()
            img.onload = () => {
              loadedCount++
              tempCache[i + 1] = imgPath
              
              // 当加载了足够多的图片后，可以开始动画了
              if (loadedCount >= Math.min(10, props.frames - 1)) {
                emit('ready', { loadedCount: loadedCount + 1, totalCount: props.frames })
              }
              
              resolve()
            }
            img.onerror = () => {
              console.error(`[SequenceImage] Failed to load image: ${imgPath}`)
              resolve()
            }
            img.src = imgPath
          })
        })
        
        // 等待所有剩余图片加载完成
        await Promise.all(loadPromises)
        
        // 过滤掉未加载的图片并更新缓存
        imageCache.value = tempCache.filter(item => item !== undefined)
        console.log(`[SequenceImage] Successfully loaded ${imageCache.value.length} images`)
        emit('ready', { loadedCount: imageCache.value.length, totalCount: props.frames })
      } catch (error) {
        console.error('[SequenceImage] Error loading images with pattern:', error)
        emit('error', error)
      }
    }

    // 预加载图片
    const preloadImages = async () => {
      if (props.useGlob) {
        await loadImagesWithGlob()
      } else {
        await loadImagesWithPattern()
      }
    }

    // 使用requestAnimationFrame优化动画
    const animateFrame = (timestamp) => {
      if (!animationInterval.value) return
      
      // 限制帧率
      const frameInterval = 1000 / props.frameRate
      const elapsed = timestamp - (animationInterval.value.lastTimestamp || 0)
      
      if (elapsed >= frameInterval) {
        // 平滑处理帧转换
        if (currentFrame.value >= imageCache.value.length - 1) {
          if (props.loop) {
            // 循环播放，回到第一帧
            currentFrame.value = 0
            emit('frame-change', { frame: currentFrame.value, total: imageCache.value.length })
          } else {
            // 不循环，停止动画
            stopAnimation()
            emit('complete')
          }
        } else {
          // 正常帧进展
          currentFrame.value += 1
          emit('frame-change', { frame: currentFrame.value, total: imageCache.value.length })
        }
        
        animationInterval.value.lastTimestamp = timestamp
      }
      
      animationFrameId = requestAnimationFrame(animateFrame)
    }

    // 启动动画
    const startAnimation = () => {
      // 如果动画已经在运行，先停止
      if (animationInterval.value) {
        stopAnimation()
      }
      
      // 如果图片缓存为空，先预加载图片
      if (imageCache.value.length === 0) {
        preloadImages()
        
        // 设置一个检查器，等待图片加载完成后再启动动画
        const checkReadyInterval = setInterval(() => {
          if (isAnimationReady.value && imageCache.value.length > 0) {
            clearInterval(checkReadyInterval)
            
            // 重置帧计数并启动动画
            currentFrame.value = 0
            animationInterval.value = { 
              active: true,
              lastTimestamp: 0
            }
            animationFrameId = requestAnimationFrame(animateFrame)
          }
        }, 100)
      } else {
        // 图片已加载，直接启动动画
        animationInterval.value = { 
          active: true,
          lastTimestamp: 0
        }
        animationFrameId = requestAnimationFrame(animateFrame)
      }
    }
    
    // 停止动画
    const stopAnimation = () => {
      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId)
        animationFrameId = null
      }
      animationInterval.value = null
    }
    
    // 重置动画
    const resetAnimation = () => {
      stopAnimation()
      currentFrame.value = 0
    }
    
    // 跳转到指定帧
    const goToFrame = (frame) => {
      currentFrame.value = Math.min(Math.max(0, frame), imageCache.value.length - 1)
    }
    
    // 处理图片加载错误
    const handleImageError = () => {
      imageError.value = true
      isLoading.value = false
      emit('error', 'Image loading failed')
    }
    
    // 处理图片加载完成
    const handleImageLoad = () => {
      imageError.value = false
      isLoading.value = false
    }
    
    // 处理页面可见性变化
    const handleVisibilityChange = () => {
      if (document.hidden) {
        // 页面不可见时暂停动画
        if (animationInterval.value) {
          stopAnimation()
        }
      } else {
        // 页面可见时恢复动画
        if (props.autoPlay && !animationInterval.value) {
          startAnimation()
        }
      }
    }
    
    // 监听props变化
    watch(() => props.frames, () => {
      resetAnimation()
      preloadImages()
    })
    
    watch(() => props.pathPattern, () => {
      resetAnimation()
      preloadImages()
    })
    
    watch(() => props.globPattern, () => {
      if (props.useGlob) {
        resetAnimation()
        preloadImages()
      }
    })
    
    // 生命周期钩子
    onMounted(() => {
      if (props.autoPlay) {
        startAnimation()
      } else {
        preloadImages()
      }
      
      // 添加可见性变化监听
      document.addEventListener('visibilitychange', handleVisibilityChange)
    })
    
    onBeforeUnmount(() => {
      stopAnimation()
    })
    
    onUnmounted(() => {
      // 移除事件监听器
      document.removeEventListener('visibilitychange', handleVisibilityChange)
    })
    
    // 暴露方法给父组件
    return {
      currentFrame,
      currentImage,
      isAnimationReady,
      opacity,
      containerStyle,
      imageStyle,
      startAnimation,
      stopAnimation,
      resetAnimation,
      goToFrame,
      handleImageError,
      handleImageLoad,
      isLoading,
      imageError
    }
  }
}
</script>

<style scoped>
.sequence-image-container {
  position: relative;
  overflow: hidden;
}

.sequence-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.loading-indicator {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(255, 255, 255, 0.2);
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(0, 0, 0, 0.1);
  border-radius: 50%;
  border-top-color: #09f;
  animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
</style>
